﻿//data bind
(function($) {
	$.fn.dataBind = function(templete, data, opts) {
		opts = jQuery.extend({
			page_container : '',
			page_size : 0,
			initial_page : 0,
			empty_text : '',
			page_animation : '',
			page_animation_start : {},
			page_animation_end : {},
			page_animation_duration : 500,
			page_changed : function(page_index, d) {
			},
			page_suspended : false
		}, opts || {});
		var backup = null;
		var items = data || [];
		var currentpage = opts.initial_page;
		var datasource = data;
		var pageContainers = $(opts.page_container);
		var container = this;

		var pagechange_callback = function(page_index) {
			if(opts.page_animation != '') {
				container.hide();
			}

			currentpage = page_index;
			datasource = items.slice(page_index * opts.page_size, (page_index + 1) * opts.page_size);
			setTemplate(container, templete, datasource);
			opts.page_changed(page_index, datasource);
			switch (opts.page_animation) {
				case 'fadein':
					container.fadeIn(opts.page_animation_duration);
					break;
				case 'slidedown':
					container.slideDown(opts.page_animation_duration);
					break;
				case '':
					break;
				default:
					container.show();
					break;
			}

			container.css(opts.page_animation_start).animate(opts.page_animation_end, opts.page_animation_duration);

			return false;
		}
		var updatepagination = function() {
			if(!opts.page_suspended) {
				if(opts.page_size > 0 && items.length > opts.page_size) {
					$(opts.page_container).pagination(items.length, {
						callback : function(page_index, jq) {
							pagechange_callback(page_index);
						},
						current_page : currentpage,
						items_per_page : opts.page_size,
						num_display_entries : 5,
						num_edge_entries : 2,
						prev_text : '<',
						next_text : '>'
					});
				} else {
					$(opts.page_container).empty();
				}

				opts.page_changed(currentpage, datasource);
			}
		}
		var setTemplate = function(container, templatetext, data) {
			container.setTemplate(templatetext, null, {
				filter_data : false
			});
			container.processTemplate(data);
		}
		var bindcurrentpage = function() {
			if(!opts.page_suspended) {
				if(items.length > 0) {
					if(opts.page_size > 0)
						datasource = items.slice(currentpage * opts.page_size, (currentpage + 1) * opts.page_size);
					else
						datasource = items;
					setTemplate(container, templete, datasource);
				} else {
					container.html(opts.empty_text);
				}
			}
		}
		bindcurrentpage();
		updatepagination();

		this.bind('filter', function(event, field, keyword) {
			if(backup == null)
				backup = items;
			items = [];
			var rg = new RegExp(keyword, 'i');

			var l = backup.length;
			var filter;

			if( typeof field == "string") {
				if(keyword == null || keyword == "")
					field = false;
				else
					filter = function(data) {
						return keyword == null || keyword == "" || data[field].search(rg) != -1;
					};
			} else
				filter = field;

			if(field)
				for(var i = 0; i < l; i++) {
					if(filter(backup[i]))
						items.push(backup[i]);
				}
			else {
				items = backup;
				backup = null;
			}

			currentpage = 0;
			bindcurrentpage();
			updatepagination();
		});

		var _update = function(model, list, ignoreNull, idField) {
			if(list) {
				var count = list.length;
				for( i = 0; i < count; i++) {
					if(list[i] && list[i][idField] && list[i][idField] == model[idField]) {
						list[i] = ignoreNull ? jQuery.extend(list[i], model) : model;

						break;
					}
				}
			}
		}

		this.bind('update', function(event, model, triggerOpts) {

			triggerOpts = jQuery.extend({
				id : "ID",
				ignoreNull : true
			}, triggerOpts || {});

			if(model && model[triggerOpts.id]) {
				_update(model, items, triggerOpts.ignoreNull, triggerOpts.id);
				_update(model, backup, triggerOpts.ignoreNull, triggerOpts.id);

				bindcurrentpage();
			}
		});

		this.bind('insert', function(event, model, triggerOpts) {
			triggerOpts = jQuery.extend({
				index : 0
			}, triggerOpts || {});

			var index = triggerOpts.index;
			if( typeof index == "string") {
				switch (index) {
					case "e":
						index = items.length;
						break;
					case "bp":
						index = opts.page_size * currentpage;
						break;
					case "ep":
						index = items.length >= opts.page_size ? opts.page_size * (currentpage + 1) - 1 : items.length;
						break;
					default:
						index = 0;
						break;
				}
			}

			items.splice(index, 0, model);
			if(backup)
				backup.splice(index, 0, model);

			currentpage = Math.floor(index / opts.page_size);

			bindcurrentpage();
			updatepagination();
		});

		var _delete = function(id, list, idField) {
			if(list) {
				var count = list.length;
				for(var i = 0; i < count; i++) {
					if(list[i] && list[i][idField] && list[i][idField] == id) {
						list.splice(i, 1);
						break;
					}
				}
			}
		};

		this.bind('delete', function(event, id, triggerOpts) {

			triggerOpts = jQuery.extend({
				id : "ID"
			}, triggerOpts || {});

			_delete(id, items, triggerOpts.id);
			_delete(id, backup, triggerOpts.id);

			if(currentpage >= Math.ceil(items.length / opts.page_size))
				currentpage = currentpage - 1;

			bindcurrentpage();
			updatepagination();
		});

		this.bind('goto', function(event, page_index) {
			pagechange_callback(page_index);
		});

		this.bind('sort', function(event, field, direction, type) {
			direction |= 1;
			type = type || "string";

			var convertValue = function(val) {
				switch (type) {
					case 'number':
						return parseFloat(val);
					case 'string':
						return val;
					case 'datetime':
						return $d.datetime.format(val);
					default:
						return $d.datetime.format(val, null, type);
				}
			};

			var _getvalue = function(name, obj) {
				var names = name.split(".")
				var l = names.length;
				var target = obj;
				for(var i = 0; i < l; i++) {
					target = target[names[i]];
				}

				return target;
			};

			items = items.sort(function(a, b) {
				if( typeof field == "string")
					return (convertValue(_getvalue(field, a)) < convertValue(_getvalue(field, b)) ? -1 : 1) * direction;
				else
					return field(a, b);
			});

			currentpage = 0;
			bindcurrentpage();
			updatepagination();
		});

		this.bind('suspend', function(event, suspended) {
			opts.page_suspended = suspended;
			if(!opts.page_suspended) {
				bindcurrentpage();
				updatepagination();
			}
		});
	}
})(jQuery);
